<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>接口定义</title>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
    <script src="../js/jquery.min.js" type="text/javascript"></script>
    <script src="../js/ClientService.js" type="text/javascript"></script>
    <script src="../js/bootstrap.min.js" type="text/javascript"></script>
    <script src="../js/bootstrap-select.js" type="text/javascript"></script>
    <script src="../js/common-yd.js" type="text/javascript"></script>
    <script src="../js/table-yd.js" type="text/javascript"></script>
    <script src="../../utils/CommonUtil.js" type="text/javascript"></script>
    <link href="../css/bootstrap.min.css" rel="stylesheet"></link>
    <link href="../css/icon.css" rel="stylesheet"></link>
    <link href="../css/bootstrap-select.css" rel="stylesheet"></link>
    <link href="../css/common-yd.css" rel="stylesheet"></link>
    <link href="../css/table-yd.css" rel="stylesheet"></link>
    <link href="../css/EPRIS.css" rel="stylesheet"></link>
    <style type="text/css">
        #serverSearchInput, #tableSearchInput {
            padding-right: 28px;
            background: url(../images/btn_query.png);
            background-size: 26px;
            background-position: 190px 1px;
            background-repeat: no-repeat;
        }

        .serverListItem {
            height: 34px;
            width: 100%;
            line-height: 34px;
            padding: 0 5px 0 15px;
            font-size: 14px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .operateBtnCommon {
            height: 32px;
            width: 90px;
            border: 1px solid #197BFF;
            border-radius: 4px;
            line-height: 30px;
            text-align: center;
            cursor: pointer;
            color: #197BFF;
            font-size: 16px;
        }

        .selfTreeNode:hover {
            background: #eaf2ff;
            color:#000000;
        }

        .selectSelfTreeNode{
            background:#b5b5e9;
            color:#FFFFFF;
        }

        .modelDefineTab {
            margin: 0 0 0 10px;
            height: 36px;
            line-height: 45px;
            border-bottom: 2px solid transparent;
            font-size: 14px;
            font-weight: normal;
            cursor: pointer;
            color: #000
        }

        .modelDefineSelectTab {
            border-bottom: 2px solid #197BFF;
            color: #197BFF;
        }

        #dragTableViewDiv {
            position: absolute;
            height: 24px;
            line-height: 24px;
            width: auto;
            font-size: 16px;
            color: #197BFF;
            background: url(../images/rxtree_child_focus.png);
            background-repeat: no-repeat;
            background-size: 22px;
            background-position: 2px 1px;
            padding-left: 26px;
            display: none;
        }

        .modelTableItem {
            position: absolute;
            height: 260px;
            width: 160px;
            background: #fff;
            border: 1px solid #197BFF;
        }

        .modelTableTitle {
            height: 30px;
            width: 100%;
            /*background: #0E1837;*/
            border-bottom: 1px solid #000;
            line-height: 30px;
            padding-left: 30px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            background-image: url(../images/field_table.png);
            background-repeat: no-repeat;
            background-size: 30px;
            cursor: grab;
        }

        .modelTableColumn {
            width: 100%;
            height: auto;
            overflow-x: hidden;
            overflow-y: auto;
            cursor: pointer;
        }

        /*拖拽调整大小*/
        .modelTableJust {
            position: absolute;
            width: 6px;
            height: 6px;
            background: #197bfd;
            display: none;
        }

        .stringTableColumn {
            height: 26px;
            width: 100%;
            line-height: 26px;
            padding-left: 30px;
            color: #3B88F2;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            background-image: url(../images/field_string_blue.png);
            background-repeat: no-repeat;
            background-size: 20px;
            background-position: 5px 3px;
            border-bottom: 1px solid #7373CD;
        }

        .numberTableColumn {
            height: 26px;
            width: 100%;
            line-height: 26px;
            padding-left: 30px;
            color: #7EBB5B;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            background-image: url(../images/field_number_green.png);
            background-repeat: no-repeat;
            background-size: 20px;
            background-position: 5px 3px;
            border-bottom: 1px solid #7373CD;
        }

        .dateTableColumn {
            height: 26px;
            width: 100%;
            line-height: 26px;
            padding-left: 30px;
            color: #3B88F2;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            background-image: url(../images/field_time_blue.png);
            background-repeat: no-repeat;
            background-size: 20px;
            background-position: 5px 3px;
            border-bottom: 1px solid #7373CD;
        }

        .textTableColumn {
            height: 26px;
            width: 100%;
            line-height: 26px;
            padding-left: 30px;
            color: #3B88F2;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            background-image: url(../images/field_text_blue.png);
            background-repeat: no-repeat;
            background-size: 20px;
            background-position: 5px 3px;
            border-bottom: 1px solid #7373CD;
        }

        .tableMenuItem {
            height: 30px;
            width: 100%;
            cursor: pointer;
            background-repeat: no-repeat;
            background-position: 5px 5px;
            background-size: 20px;
        }

        .tableMenuItem:hover {
            background: #eaf2ff;
            background-repeat: no-repeat;
            background-position: 5px 5px;
            background-size: 20px;
        }

        .tableMenuItem > li {
            height: 30px;
            line-height: 30px;
            padding-left: 27px;
            text-indent: 1px;
            list-style: none;
        }

        .selectTableMenuItem > li {
            padding-left: 10px;
            list-style: disc;
        }

        #addNewBtnMenu{
            position: absolute;
            width: 122px;
            height: 82px;
            border: 1px solid #dedede;
            background: #fff;
            display: none;
        }
        #addNewBtnMenu>div{
            height:40px;
            width:120px;
            cursor:pointer;
            padding-left:24px;
            line-height: 40px;
            font-size: 14px;
            background-repeat: no-repeat;
            background-position: 5px;
        }
        #addNewBtnMenu>div:hover{
            background-color: #c6e2ff;
            color:#197BFD;
        }
        .modelTreeOper{
            height:30px;
            width:110px;
            cursor:pointer;
        }
        .modelTreeOper:hover{
            background:#ECF4FC;
        }
    </style>
</head>
<body onload="refreshPageElement()" onresize="refreshPageElement()" onselectstart="return false;">
<div id="existServerArea" style="float:left;width:240px;height:100%;border-right:1px solid #197BFF;">
    <div style="height:50px;width:239px;font-size:16px;line-height:50px;text-align:left;padding-left:10px;">
        <div style="float:left;width:30px;height:50px;background:url(../images/server_menu.png);background-size:28px;background-repeat:no-repeat;background-position:center;"></div>
        <div style="float:left;width:169px;height:50px;line-height:50px;font-size:16px;color:#197BFF;">数据模型管理</div>
        <div style="float:left;width:20px;height:30px;margin-top:15px;margin-right:10px;">
            <img onclick="showAddNewBtnMenu(this)" src="../images/server_add.png" style="width:20px;height:20px;cursor:pointer;"/>
        </div>
    </div>
    <div style="height:40px;width:239px">
        <input id="serverSearchInput" onKeyup="changeServerSearch()" style="height:30px;width:219px;margin:5px 9px;" type="text"/>
    </div>
    <div id="serverListArea" style="width:239px;height:calc(100% - 90px);overflow-y:auto;overflow-x:hidden;"></div>
</div>
<div id="emptyCenterArea" style="float:left;height:100%;width:calc(100% - 240px);">
    <div style="height:300px;width:260px;margin-left:calc(50% - 130px);margin-top:calc(25% - 150px);">
        <div style="height:260px;width:260px;background-image:url(../images/server_menu.png);background-size:260px;"></div>
        <div style="height:40px;width:260px;font-size:20px;color:#197BFF;">请在左侧新建或选择数据模型</div>
    </div>
</div>
<div id="editCenterArea" style="float:left;height:100%;width: calc(100% - 240px);display:none;">
    <div id="serverDefineArea" style="width:100%;height:100%;">
        <div style="float:left;width:240px;height:100%;border-right:1px solid #197BFF;">
            <div style="height:36px;width:239px;line-height:36px;text-align:center;font-size:16px;color:#197BFF;">
                数据源表选择
            </div>
            <div style="height:40px;width:239px;padding:5px 9px;">
                <div style="float:left;height:30px;width:189px;border:1px solid #197BFD;border-radius:5px;">
                    <select id="dsConnectCombo" class="selectpicker selectdiv" data-width="189px" style="width:190px;height:30px;" title=""></select>
                </div>
                <div style="float:left;width:29px;height:30px;padding-top:3px;padding-left:3px;">
                    <img onclick="refreshDSConnectCombo()" src="../images/server_refresh.png" style="height:24px;height:24px;cursor:pointer;"/>
                </div>
            </div>
            <div style="height:40px;width:239px">
                <input id="tableSearchInput" onKeyup="changeTableSearch()" style="height:30px;width:219px;margin:5px 9px;" type="text"/>
            </div>
            <div id="dsTableTreeArea" style="width:239px;height:calc(100% - 116px);overflow:auto;"></div>
        </div>
        <div id="modelDefineArea" style="float:left;height:100%;width:calc(100% - 240px);">
            <div style="height:46px;width:100%;">
                <label class="modelDefineTab modelDefineSelectTab" onclick="showModelDefineCreate(this)">数据模型</label>
                <label class="modelDefineTab" onclick="showModelDefineDatas(this)">明细页</label>
                <label class="modelDefineTab" onclick="showModelDefineSQL(this)">SQL页</label>
                <div class="operateBtnCommon" onclick="saveInterfaceDefine()" style="float:right;margin:7px 5px;width:110px;">数据模型保存</div>
            </div>
            <div id="modelTableEdit" style="position:relative;width:100%;height:calc(100% - 46px);border-top: 1px solid #197bff">
                <div id="modelDefineCreateDiv" style="position:relative;width:100%;height:100%;background:url(../images/grid_dotted.png)">
                    <canvas id="tableRelaCanvas" style="position:absolute;width:100%;height:100%;top:0px;left:0px;"></canvas>
                    <div id="modelDefineTableArea" style="position:absolute;width:100%;height:100%;top:0px;left:0px;"></div>
                    <div id="tableJoinMenu" style="position:absolute;height:128px;width:120px;border:1px solid #197BFF;border-radius:4px;background-color: white;display:none;">
                        <div class="tableMenuItem selectTableMenuItem" onclick="changeTableJoinType(0)" type='0'>
                            <li>内连接（默认）</li>
                        </div>
                        <div class="tableMenuItem" onclick="changeTableJoinType(1)" type='1'>
                            <li>左连接</li>
                        </div>
                        <div class="tableMenuItem" onclick="changeTableJoinType(2)" type='2'>
                            <li>右连接</li>
                        </div>
                        <div style="height:1px;margin:4px 4px 1px 4px;border-bottom:1px solid #197BFF;width:110px;"></div>
                        <div class="tableMenuItem" onclick="deleteTableJoins()" style="line-height:30px;background-image:url(../images/delete_blue.png);padding-left:28px;">
                            删除
                        </div>
                    </div>
                    <div id="tableTitleMenu" style="position:absolute;height:68px;width:120px;border:1px solid #197BFF;background-color: white;border-radius:4px;display:none;">
                        <div class="tableMenuItem" onclick="filterModelTable()" style="line-height:30px;background-image:url(../images/filter_blue.png);padding-left:28px;">
                            过滤设置
                        </div>
                        <div style="height:1px;margin:4px 4px 1px 4px;border-bottom:1px solid #197BFF;width:110px;"></div>
                        <div class="tableMenuItem" onclick="deleteModelTable()" style="line-height:30px;background-image:url(../images/delete_blue.png);padding-left:28px;">
                            删除
                        </div>
                    </div>
                </div>
                <div id="modelDefineDatasDiv" style="width:100%;height:100%;display:none;"></div>
                <div id="modelDefineSQLDiv" style="width:100%;height:100%;overflow:auto;display:none;"></div>
            </div>
        </div>
    </div>
</div>
<div id="dragTableViewDiv"></div>
<div id="addNewBtnMenu">
    <div style="background-image: url(../images/rxtree_child_focus.png);" onclick="addRootDataModel()">新建数据模型</div>
    <div style="background-image: url(../images/rxtree_parent_focus.png);" onclick="addRootModelFolder()">新建文件夹</div>
</div>
<div id="dataModelOperList" style="position:absolute;width:116px;height:auto;padding:2px;top:0;left:0;background:#FFFFFF;border:1px solid #D6D6D6;display:none;">
	<div id="addModelTreeFolder" class="modelTreeOper" onclick="addModelTreeFolder()">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/rxtree_parent_focus.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">新建文件夹</div>
	</div>
	<div id="addModelTreeNode" class="modelTreeOper" onclick="addModelDataModel()">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/rxtree_child_focus.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:72px;line-height:30px;">新建数据模型</div>
	</div>
	<div class="modelTreeOper" onclick="editModelNodeName()">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/edit_blue.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">重命名</div>
	</div>
	<!--<div class="modelTreeOper" style="border-top:1px solid #D6D6D6;" onclick="pageForm.moveJobNodeTo()">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/moveto_blue.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">移动到...</div>
	</div>-->
	<div class="modelTreeOper" style="border-top:1px solid #D6D6D6;" onclick="sortModelTreeNode('1')">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/moveup_blue.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">上移</div>
	</div>
	<div class="modelTreeOper" onclick="sortModelTreeNode('2')">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/movedown_blue.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">下移</div>
	</div>
	<div class="modelTreeOper" style="border-top:1px solid #D6D6D6;" onclick="deleteModelTreeNode()">
		<div style="float:left;height:30px;width:30px;padding:6px;"><img src="../images/delete_blue.png" style="height:18px;width:18px;"></div>
		<div style="float:left;height:30px;width:60px;line-height:30px;">删除</div>
	</div>
</div>
<div id="modelNameEditDiv" class="windowCommon" style="width:300px;height:180px;">
	<div class="windowTitleCommon" style="height:30px;width:300px;">
		<div id="editNameTitle" class="windowTitleTextCommon" style="width:268px;height:30px;line-height:30px;"></div>
		<div class="windowTitleCloseCommon" style="width:18px;height:30px;padding-top:6px;">
			<img class="windowCloseImageCommon" src="../images/close_grey.png" onclick="hideCustomWindow()">
		</div>
	</div>
	<div class="windowContentCommon" style="height:98px;width:296px;">
        <input id='modelNodeNameEditor' class="inputCommon" tyle='text' style="height:30px;width:220px;margin:34px 36px;border:1px solid #197BFD;">
	</div>
	<div style="height:50px;width:300px;text-align:right;padding-top:12px;padding-right:10px;border-top:1px solid #197BFD;">
		<input class="btnCommon btnClose" type="button" value="关闭" onclick="hideCustomWindow()"/>
		<input class="btnCommon btnSure" type="button" value="确定" onclick="saveModelNodeName()"/>
	</div>
</div>
<script type="text/javascript">
    var serverID = null;
    var serverGroup = null;
    var initCount = 0;
    var mouseX = 0, mouseY = 0;
    var isDragTable = false, isDragModel = false;
    var tableIndex = 1;
    var tableFilter = {};
    var dragModelEle = null;
    var resizeTableType = null;
    var isDrawJoin = false, startJoinCol = null, tableJoinMap = {}, tableJoinPoint = {};
    var drawJoinCanvas = null;
    var hoverTableLine = null;
    var modelDefine = null, viewTable = null;
    //iframe传值
    window.addEventListener('message', function (event) {
        baseURL = event.data;
        drawJoinCanvas = document.getElementById('tableRelaCanvas');
        bindDocumentEvent();
        refreshPageElement();
        refreshExistServer();
        refreshDSConnectCombo();
    });

    function refreshExistServer() {
        $.ajax({
            url: "dataSourceController/getExistDataModel",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                if(data.respStatus){
                    $('#serverListArea').html("<ul class='selfTreeUL' style='width:100%;'></ul>");
                    for (var i = 0; i < data.respData.length; i++) {
                        var nodeInfo = data.respData[i];
                        var id = nodeInfo[0], pid = nodeInfo[1], nodeCode = nodeInfo[2], nodeName = nodeInfo[3], nodePCode = nodeInfo[4], isLeaf = nodeInfo[5];
                        var parentNode = $('#serverListArea').find('#' + pid);
                        var checkNodeClass = ('D_'+serverID)==id?' selectSelfTreeNode':'';
                        var nodeHTML = "<li class='selfTreeLI' style='min-width:100%;'>"
                                     + "    <div id='" + id + "' pid='"+pid+"' class='selfTreeNode"+checkNodeClass+"' style='padding-left:5px;' isLeaf= '"+isLeaf+"' code='"+nodeCode+"' pcode='"+nodePCode+"'>"
                                     + "        <div class='selfTreeToggle' style='background-image:url(../images/rxtree_plus.png)'"
                                     + "             onclick='toggleTableTree(this)'></div>"
                                     + "        <div class='selfTreeImage' style='background-image:url(../images/rxtree_"+(isLeaf=='0'?"parent":"child")+"_focus.png)'></div>"
                                     + "        <div class='selfTreeText'>" + nodeName + "</div>"
                                     + "    </div>"
                                     + "    <ul class='selfTreeUL' style='width:100%;display:none;padding-left:16px;'></ul>"
                                     + "</li>";
                        if (parentNode.length == 0) {
                            $('#serverListArea>.selfTreeUL').append(nodeHTML);
                        }else{
                            parentNode.find('.selfTreeToggle').css('visibility', 'visible');
                            parentNode.parent().children('.selfTreeUL').append(nodeHTML);
                        }
                    }
                    bindServerTreeEvent();
                    if(serverID!=null){
                        var serverPID = $('#serverListArea').find('#D_'+serverID).attr('pid');
                        while(serverPID&&serverPID!=''){
                            $('#serverListArea').find('#'+serverPID).find('.selfTreeToggle').click();
                            serverPID = $('#serverListArea').find('#'+serverPID).attr('pid');
                        }
                    }
                }else{
                    showWarnDialog(data.respMessage);
                }
            }
        });
    }

    function bindServerTreeEvent(){
        $('#serverListArea').find('.selfTreeNode[isLeaf="1"]').unbind();
        $('#serverListArea').find('.selfTreeNode[isLeaf="1"]').click(function(e){
            if(serverID==$(this).attr('code')){
                return;
            }
            serverID = $(this).attr('code');
            serverGroup = $(this).attr('pcode');
            $('#serverListArea').find('.selfTreeNode').removeClass("selectSelfTreeNode");
            $(this).addClass('selectSelfTreeNode');
            reshowServerSetting(serverID);
        });
        $('#serverListArea').find('.selfTreeNode').contextmenu(function(e){
            var nodeType = $(this).attr('isLeaf');
            if(nodeType=='0'){//文件夹
                $('#addModelTreeFolder,#addModelTreeNode').show();
            }else if(nodeType=='1'){//模型
                $('#addModelTreeFolder,#addModelTreeNode').hide();
            }
            $('#dataModelOperList').attr('nodeID', $(this).attr('id')).css({left:e.pageX+2,top:e.pageY+2}).show();
            e.preventDefault();
        })
    }

    function changeServerSearch() {
        var inputVal = $.trim($('#serverSearchInput').val());
        $('#serverListArea').find('.selfTreeNode[isLeaf="1"]').each(function(e){
            var thisName = $.trim($(this).find('.selfTreeText').text());
            if (inputVal == "" || thisName.indexOf(inputVal) != -1) {
                $(this).show();
            } else {
                $(this).hide();
            }
        });
    }

    function showAddNewBtnMenu(clickEle){
        var menuLeft = $(clickEle).offset().left;
        var menuTop = $(clickEle).offset().top;
        $('#addNewBtnMenu').css({left:menuLeft, top:menuTop+20}).show();
    }

    function addRootModelFolder(){
        $('#editNameTitle').text("新增文件夹");
        $('#addNewBtnMenu').hide();
        $('#modelNodeNameEditor').val('');
        $('#modelNameEditDiv').attr('editType', '1').attr('isLeaf', '0').attr('nodeID', '');
        showCustomWindow($('#modelNameEditDiv'));
    }

    function addModelTreeFolder(){
        $('#dataModelOperList').hide();
        $('#editNameTitle').text("新增文件夹");
        $('#modelNodeNameEditor').val('');
        var nodeCode = $('#serverListArea').find('#'+$('#dataModelOperList').attr('nodeID')).attr('code');
        $('#modelNameEditDiv').attr('editType', '1').attr('isLeaf', '0').attr('nodeID', nodeCode);
        showCustomWindow($('#modelNameEditDiv'));
    }

    function editModelNodeName(){
        $('#dataModelOperList').hide();
        $('#editNameTitle').text("重命名");
        var editNodeID = $('#dataModelOperList').attr('nodeID');
        var nodeCode = $('#serverListArea').find('#'+editNodeID).attr('code');
        $('#modelNodeNameEditor').val($.trim($('#serverListArea').find('#'+editNodeID).text()));
        $('#modelNameEditDiv').attr('editType', '2').attr('isLeaf', $('#serverListArea').find('#'+editNodeID).attr('isLeaf')).attr('nodeID', nodeCode);
        showCustomWindow($('#modelNameEditDiv'));
    }

    function saveModelNodeName(){
        var editType = $('#modelNameEditDiv').attr('editType');
        var isLeaf = $('#modelNameEditDiv').attr('isLeaf');
        var nodeID = $('#modelNameEditDiv').attr('nodeID');
        var editName = $('#modelNodeNameEditor').val();
        if(checkEmpty(editName)) return showWarnDialog("名称不可为空！");
        $.ajax({
            url: "dataSourceController/saveModelNodeName",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({editType:editType, nodeID:nodeID, editName:editName, isLeaf:isLeaf}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                if(data.respStatus){
                    refreshExistServer();
                    hideCustomWindow();
                    showAutoCloseDialog(data.respMessage);
                }else{
                    showWarnDialog(data.respMessage);
                }
            }
        });
    }

    function addRootDataModel() {
        $('#addNewBtnMenu').hide();
        $('#serverListArea').find('.selectSelfTreeNode').removeClass('selectSelfTreeNode');
        clearInterfaceSetInfo();
        $('#emptyCenterArea').hide();
        $('#editCenterArea').show();
        refreshPageElement();
    }

    function addModelDataModel(){
        $('#dataModelOperList').hide();
        $('#serverListArea').find('.selectSelfTreeNode').removeClass('selectSelfTreeNode');
        clearInterfaceSetInfo();
        $('#emptyCenterArea').hide();
        $('#editCenterArea').show();
        var groupPID = $('#dataModelOperList').attr('nodeID');
        serverGroup = $('#serverListArea').find('#'+groupPID).attr('code');
        refreshPageElement();
    }

    function sortModelTreeNode(sortType){
        $('#dataModelOperList').hide();
        var menuID = $('#dataModelOperList').attr('nodeID');
        var nodeID = $('#serverListArea').find('#'+menuID).attr('code');
        var nodeGroup = $('#serverListArea').find('#'+menuID).attr('pcode');
        var isLeaf = $('#serverListArea').find('#'+menuID).attr('isLeaf');
        if(sortType=="1"){//上移
            var prevNodeEle = $('#serverListArea').find('#'+menuID).parent().prev();
            if(prevNodeEle.length==0||prevNodeEle.find('.selfTreeNode').attr('isLeaf')!=isLeaf) return showWarnDialog("已是最前节点，不可上移");
        }else if(sortType=="2"){//下移
            var nextNodeEle = $('#serverListArea').find('#'+menuID).parent().next();
            if(nextNodeEle.length==0||nextNodeEle.find('.selfTreeNode').attr('isLeaf')!=isLeaf) return showWarnDialog("已是最下节点，不可下移");
        }
        $.ajax({
            url: "dataSourceController/moveModelNodeOrder",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({moveType:sortType, moveID:nodeID, moveGroup:nodeGroup, nodeType:isLeaf}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                if(data.respStatus){
                    refreshExistServer();
                    hideCustomWindow();
                    showAutoCloseDialog(data.respMessage);
                }else{
                    showWarnDialog(data.respMessage);
                }
            }
        });
    }

    function deleteModelTreeNode(){
        $('#dataModelOperList').hide();
        var menuID = $('#dataModelOperList').attr('nodeID');
        var nodeID = $('#serverListArea').find('#'+menuID).attr('code');
        var isLeaf = $('#serverListArea').find('#'+menuID).attr('isLeaf');
        if($('#serverListArea').find('#'+menuID).next().find('li').length>0) return showWarnDialog("存在下级节点，请先删除下级后再删除");
        $.ajax({
            url: "dataSourceController/deleteDataModel",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({nodeType:isLeaf, nodeCode:nodeID}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                if(data.respStatus){
                    if(nodeID==serverID){
                        clearInterfaceSetInfo();
                        $('#emptyCenterArea').show();
                        $('#editCenterArea').hide();
                    }
                    refreshExistServer();
                    showAutoCloseDialog(data.respMessage);
                }else{
                    showWarnDialog(data.respMessage);
                }
            }
        });
    }

    function reshowServerSetting(serverNO) {
        $.ajax({
            url: "dataSourceController/getExistServerSet",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({"nodeID": serverNO}),
            contentType: "application/json",
            success: function (data) {
                $('#emptyCenterArea').hide();
                $('#editCenterArea').show();
                refreshPageElement();
                clearInterfaceSetInfo();
                //serverID, serverInfo, tableInfo, tableColInfo, tableJoinInfo, tableFilterInfo
                serverID = data.respData.serverID;
                //{serverNO, serverName, serverDesc, dsNO, groupCode}
                var serverInfo = data.respData.serverInfo;
                serverGroup = serverInfo.groupCode;
                $("#dsConnectCombo").selectpicker('val', serverInfo.dsNO);
                $('#dsConnectCombo').change();
                //[[colName, colComment, colType, colAlias, tableName, tableComment, tableTemp, dsNO, sortNO],...]
                var tableColInfo = data.respData.tableColInfo;
                var tableColMap = {};
                var allColHTML = "";
                for (var i = 0; i < tableColInfo.length; i++) {
                    var columnInfo = tableColInfo[i];
                    var colName = columnInfo[0], colComment = columnInfo[1], colType = columnInfo[2], tableAlias = columnInfo[6];
                    colComment = checkEmpty(colComment) ? colName : colComment;
                    var tableColList = tableColMap[tableAlias] || [];
                    tableColList.push([colName, colComment, colType]);
                    tableColMap[tableAlias] = tableColList;
                }
                //[{tableName, tableComment, tableTemp, dsNO, joinType, tableLeft, tableTop, tableSort},...]
                var tableList = data.respData.tableInfo;
                for (var i = 0; i < tableList.length; i++) {
                    var tableInfo = tableList[i];
                    var tableName = tableInfo.tableName, tableComment = tableInfo.tableComment, tableTemp = tableInfo.tableTemp;
                    var thisIndex = parseInt(tableTemp.substring(1));
                    if (thisIndex >= tableIndex) tableIndex = thisIndex + 1;
                    mouseX = tableInfo.tableLeft;
                    mouseY = tableInfo.tableTop;
                    createTableModelEle(tableName, tableTemp, tableComment, tableColMap[tableTemp])
                }
                //恢复tableJoinMap值
                //[[startTable, startTemp, startCols, startColComment, stopTable, stopTemp, stopCols, stopColComment, joinType],...]
                var tableJoinInfo = data.respData.tableJoinInfo;
                for (var i = 0; i < tableJoinInfo.length; i++) {
                    var joinInfo = tableJoinInfo[i];
                    var startTemp = joinInfo[1], startCol = joinInfo[2], stopTemp = joinInfo[5], stopCol = joinInfo[6], joinType = joinInfo[8];
                    tableJoinMap[startTemp + '.' + startCol + '-' + stopTemp + '.' + stopCol] = joinType;
                }
                //绘制关联线
                refreshCanvasRelation();
                //恢复tableFilter值
                //[[tableName, tableTemp, colCode, colComment, multiType, relaType, matchVal, sortNO],...]
                var tableFilterInfo = data.respData.tableFilterInfo;
                for (var i = 0; i < tableFilterInfo.length; i++) {
                    var filterInfo = tableFilterInfo[i];
                    var tableTemp = filterInfo[1], colCode = filterInfo[2], colComment = filterInfo[3];
                    var multiType = filterInfo[4], relaType = filterInfo[5], matchVal = filterInfo[6], sortNO = filterInfo[7];
                    var filterGroup = tableFilter[tableTemp] || [];
                    filterGroup.push([colCode, colComment, multiType, relaType, matchVal, sortNO]);
                    tableFilter[tableTemp] = filterGroup;
                }
            }
        })
    }

    function clearInterfaceSetInfo() {
        $('#modelDefineTableArea,#modelDefineDatasDiv,#modelDefineSQLDiv').empty();
        var canvas2D = drawJoinCanvas.getContext("2d");
        canvas2D.clearRect(0, 0, drawJoinCanvas.width, drawJoinCanvas.height);
        $('.modelDefineTab:first').click();
        serverID = null;
        serverGroup = null;
        tableIndex = 1;
        tableFilter = {};
        tableJoinMap = {};
    }

    //select下拉框
    function refreshDSConnectCombo() {
        $.ajax({
            url: "dataSourceController/getExistDSConnect",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                $('#dsConnectCombo').empty();
                for (var i = 0; i < data.respData.length; i++) {
                    var thisData = data.respData[i];
                    $('#dsConnectCombo').append("<option value='" + thisData.code + "'>" + thisData.name + "</option>");
                }
                $("#dsConnectCombo").selectpicker("refresh");
                $("#dsConnectCombo").selectpicker("setStyle", "background", "transparent");
                $("#dsConnectCombo").selectpicker('val', $('#dsConnectCombo').val());
                $('#dsConnectCombo').change(function (e) {
                    refreshDSTableArea();
                    var serverTemp = serverID;
                    var serverGroupTemp = serverGroup;
                    clearInterfaceSetInfo();
                    serverID = serverTemp;
                    serverGroup = serverGroupTemp;
                });
                refreshDSTableArea();
            },
        })
    }

    function refreshDSTableArea() {
        $('#dsTableTreeArea').empty();
        var dsNO = $('#dsConnectCombo').val();
        $.ajax({
            url: "dataSourceController/getDatabaseTables",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({dsNO: dsNO}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                $('#dsTableTreeArea').html("<ul class='selfTreeUL' style='width:100%;'></ul>");
                for (var i = 0; i < data.respData.length; i++) {
                    var moduleInfo = data.respData[i];
                    var tableName = moduleInfo[0], tableComment = moduleInfo[1];
                    var groupCode = tableName.indexOf('_') == -1 ? tableName : (tableName.substring(0, tableName.indexOf('_')));
                    var parentNode = $('#dsTableTreeArea').find('#' + groupCode);
                    if (parentNode.length == 0) {
                        var nodeHTML = "<li class='selfTreeLI' style='min-width:100%;'>"
                                    + "    <div id='" + groupCode + "' class='selfTreeNode' style='padding-left:5px;' isLeaf= '0'>"
                                    + "        <div class='selfTreeToggle' style='background-image:url(../images/rxtree_plus.png)'"
                                    + "             onclick='toggleTableTree(this)'></div>"
                                    + "        <div class='selfTreeImage' style='background-image:url(../images/rxtree_parent_focus.png)'></div>"
                                    + "        <div class='selfTreeText'>" + groupCode + "</div>"
                                    + "    </div>"
                                    + "    <ul class='selfTreeUL' style='width:100%;display:none;'></ul>"
                                    + "</li>";
                        var thisNodeHTML = $(nodeHTML);
                        $('#dsTableTreeArea>.selfTreeUL').append(thisNodeHTML);
                    }
                    var parentNode = $('#dsTableTreeArea').find('#' + groupCode);
                    var leafHTML = "<li class='selfTreeLI' style='min-width:100%;'>"
                                + "    <div id='" + tableName + "' class='selfTreeNode' style='padding-left:25px;' isLeaf= '1'>"
                                + "        <div class='selfTreeToggle' style='background-image:url(../images/rxtree_plus.png)'"
                                + "             onclick='toggleTableTree(this)'></div>"
                                + "        <div class='selfTreeImage' style='background-image:url(../images/rxtree_child_focus.png)'></div>"
                                + "        <div class='selfTreeText'>" + tableComment + "</div>"
                                + "    </div>"
                                + "</li>";
                    parentNode.find('.selfTreeToggle').css('visibility', 'visible');
                    parentNode.parent().children('.selfTreeUL').append(leafHTML);
                }
                bindDSTableTreeEvent();
            },
        });
    }

    function toggleTableTree(groupEle) {
        var childUL = $(groupEle).parent().parent().children('.selfTreeUL');
        if (childUL.is(':visible')) {
            childUL.hide();
            $(groupEle).css('background-image', 'url(../images/rxtree_plus.png)');
        } else {
            childUL.show();
            $(groupEle).css('background-image', 'url(../images/rxtree_minus_focus.png)');
        }
    }

    function changeTableSearch() {
        $('#dsTableTreeArea').find('.selfTreeLI').show();
        var inputVal = $.trim($('#tableSearchInput').val());
        var parentLI = null, childCount = 0, searchCount = 0;
        var treeNodeCount = $('#dsTableTreeArea').find('.selfTreeLI').length;
        $('#dsTableTreeArea').find('.selfTreeLI>.selfTreeNode').each(function () {
            searchCount++;
            var nodeType = $(this).attr('isLeaf');
            var tableName = $(this).attr('id'), tableComment = $.trim($(this).text());
            if (nodeType == '0') {
                if (parentLI != null) {
                    if (childCount > 0) {
                        parentLI.show();
                    } else {
                        parentLI.hide();
                    }
                }
                parentLI = $(this).parent();
                childCount = 0;
            } else {
                if (inputVal == "" || tableName.indexOf(inputVal) != -1 || tableComment.indexOf(inputVal) != -1) {
                    childCount++;
                    $(this).parent().show();
                } else {
                    $(this).parent().hide();
                }
            }
            if (searchCount == treeNodeCount) {
                if (parentLI != null) {
                    if (childCount > 0) {
                        parentLI.show();
                    } else {
                        parentLI.hide();
                    }
                }
            }
        });
    }

    function bindDocumentEvent() {
        $(document).mousemove(function (e) {
            if (isDragTable) {
                mouseX = e.pageX, mouseY = e.pageY;
                $('#dragTableViewDiv').css({top: mouseY + 2, left: mouseX + 2});
            } else if (isDragModel) {
                //鼠标移动距离
                var moveX = e.pageX - mouseX, moveY = e.pageY - mouseY;
                //元素相对位置
                var eleX = dragModelEle[0].offsetLeft, eleY = dragModelEle[0].offsetTop;
                if (moveX < 0 && eleX < Math.abs(moveX)) moveX = 0 - eleX;
                if (moveY < 0 && eleY < Math.abs(moveY)) moveY = 0 - eleY;
                dragModelEle.css({left: eleX + moveX, top: eleY + moveY});
                mouseX = mouseX + moveX;
                mouseY = mouseY + moveY;
                refreshCanvasRelation();
            } else if (resizeTableType != null) {
                var moveX = e.pageX - mouseX, moveY = e.pageY - mouseY;
                var tableWidth = dragModelEle.width(), tableHeight = dragModelEle.height();
                var tableLeft = dragModelEle[0].offsetLeft, tableTop = dragModelEle[0].offsetTop;
                if (resizeTableType == 'nw') {//左上角
                    if (moveX > 0) {//往右拖动
                        if (tableWidth - moveX < 30) moveX = tableWidth - 30;
                    } else if (moveX < 0) {//往左拖动
                        if (Math.abs(moveX) > tableLeft) moveX = 0 - tableLeft;
                    }
                    dragModelEle.width(tableWidth - moveX);
                    dragModelEle.css('left', tableLeft + moveX);
                    if (moveY > 0) {//向下
                        if (tableHeight - moveY < 32) moveY = tableHeight - 32;
                    } else if (moveY < 0) {//向上
                        if (Math.abs(moveY) > tableTop) moveY = 0 - tableTop;
                    }
                    dragModelEle.height(tableHeight - moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight - moveY - 32);
                    dragModelEle.css('top', tableTop + moveY);
                    mouseX = mouseX + moveX;
                    mouseY = mouseY + moveY;
                } else if (resizeTableType == 'n') {//上方
                    if (moveY > 0) {//向下
                        if (tableHeight - moveY < 32) moveY = tableHeight - 32;
                    } else if (moveY < 0) {//向上
                        if (Math.abs(moveY) > tableTop) moveY = 0 - tableTop;
                    }
                    dragModelEle.height(tableHeight - moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight - moveY - 32);
                    dragModelEle.css('top', tableTop + moveY);
                    mouseY = mouseY + moveY;
                } else if (resizeTableType == 'ne') {//右上角
                    if (moveX < 0) {//往左拖动
                        if (tableWidth + moveX < 30) moveX = 30 - tableWidth;
                    }
                    dragModelEle.width(tableWidth + moveX);
                    if (moveY > 0) {//向下
                        if (tableHeight - moveY < 32) moveY = tableHeight - 32;
                    } else if (moveY < 0) {//向上
                        if (Math.abs(moveY) > tableTop) moveY = 0 - tableTop;
                    }
                    dragModelEle.height(tableHeight - moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight - moveY - 32);
                    dragModelEle.css('top', tableTop + moveY);
                    mouseX = mouseX + moveX;
                    mouseY = mouseY + moveY;
                } else if (resizeTableType == 'w') {//左侧
                    if (moveX > 0) {//往右拖动
                        if (tableWidth - moveX < 30) moveX = tableWidth - 30;
                    } else if (moveX < 0) {//往左拖动
                        if (Math.abs(moveX) > tableLeft) moveX = 0 - tableLeft;
                    }
                    dragModelEle.width(tableWidth - moveX);
                    dragModelEle.css('left', tableLeft + moveX);
                    mouseX = mouseX + moveX;
                } else if (resizeTableType == 'e') {//右侧
                    if (moveX < 0) {//往左拖动
                        if (tableWidth + moveX < 30) moveX = 30 - tableWidth;
                    }
                    dragModelEle.width(tableWidth + moveX);
                    mouseX = mouseX + moveX;
                } else if (resizeTableType == 'sw') {//左下角
                    if (moveX > 0) {//往右拖动
                        if (tableWidth - moveX < 30) moveX = tableWidth - 30;
                    } else if (moveX < 0) {//往左拖动
                        if (Math.abs(moveX) > tableLeft) moveX = 0 - tableLeft;
                    }
                    dragModelEle.width(tableWidth - moveX);
                    dragModelEle.css('left', tableLeft + moveX);
                    if (moveY < 0) {//向上
                        if (tableHeight + moveY < 30) moveY = 32 - tableHeight;
                    }
                    dragModelEle.height(tableHeight + moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight + moveY - 32);
                    mouseX = mouseX + moveX;
                    mouseY = mouseY + moveY;
                } else if (resizeTableType == 's') {//下方
                    if (moveY < 0) {//向上
                        if (tableHeight + moveY < 30) moveY = 32 - tableHeight;
                    }
                    dragModelEle.height(tableHeight + moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight + moveY - 32);
                    mouseY = mouseY + moveY;
                } else if (resizeTableType == 'se') {//右下角
                    if (moveY < 0) {//向上
                        if (tableHeight + moveY < 30) moveY = 32 - tableHeight;
                    }
                    dragModelEle.height(tableHeight + moveY);
                    dragModelEle.find('.modelTableColumn').height(tableHeight + moveY - 32);
                    mouseY = mouseY + moveY;
                    if (moveX < 0) {//往左拖动
                        if (tableWidth + moveX < 30) moveX = 30 - tableWidth;
                    }
                    dragModelEle.width(tableWidth + moveX);
                    mouseX = mouseX + moveX;
                }
                mouseX = e.pageX, mouseY = e.pageY;
                refreshCanvasRelation();
            } else if (isDrawJoin) {
                mouseX = e.pageX, mouseY = e.pageY;
                refreshCanvasRelation();
            }
        }).mouseup(function (e) {
            if (isDragTable) {
                if (e.target.id == 'modelDefineTableArea' || $('#modelDefineTableArea').find(e.target).length > 0) {
                    mouseX = e.pageX - $('#modelDefineTableArea').offset().left;
                    mouseY = e.pageY - $('#modelDefineTableArea').offset().top;
                    var tableName = $('#dragTableViewDiv').attr('tableName'),
                            tableComment = $('#dragTableViewDiv').text();
                    addDSTable2Model(tableName, tableComment);
                }
                isDragTable = false;
                $('#dragTableViewDiv').hide();
            } else if (isDragModel) {
                isDragModel = false;
                dragModelEle = null;
            } else if (resizeTableType != null) {
                resizeTableType = null;
                dragModelEle = null;
            } else if (isDrawJoin) {
                if (!$(e.target).hasClass('tableColumnCommon')) {
                    isDrawJoin = false;
                    startJoinCol = null;
                    mouseX = e.pageX, mouseY = e.pageY;
                    refreshCanvasRelation();
                }
            }
        }).mousedown(function (e) {
            if ($('#tableJoinMenu').find(e.target).length == 0 && e.target.id != 'tableJoinMenu') {
                $('#tableJoinMenu').hide();
            }
            if ($('#tableTitleMenu').find(e.target).length == 0 && e.target.id != 'tableTitleMenu') {
                $('#tableTitleMenu').hide();
            }
            if($('#addNewBtnMenu').find(e.target).length==0&&e.target.id!='addNewBtnMenu'){
                $('#addNewBtnMenu').hide();
            }
            if($('#dataModelOperList').find(e.target).length==0&&e.target.id!='dataModelOperList'){
                $('#dataModelOperList').hide();
            }
        });
        $('#modelDefineCreateDiv').mousemove(function (e) {
            if (!isDrawJoin) {
                var prevHoverLine = hoverTableLine;
                hoverTableLine = null;
                var pointX = e.pageX - $('#tableRelaCanvas').offset().left;
                var pointY = e.pageY - $('#tableRelaCanvas').offset().top;
                for (var relaCode in tableJoinPoint) {
                    var relaLine = tableJoinPoint[relaCode];
                    var startPoint = relaLine[0], stopPoint = relaLine[1];
                    if (checkPointInLine(pointX, pointY, relaLine[0], relaLine[1])
                            || checkPointInLine(pointX, pointY, relaLine[1], relaLine[2])
                            || checkPointInLine(pointX, pointY, relaLine[2], relaLine[3])) {
                        hoverTableLine = relaCode;
                    }
                }
                if (prevHoverLine != hoverTableLine) {
                    mouseX = e.pageX, mouseY = e.pageY;
                    refreshCanvasRelation();
                }
            }
        }).contextmenu(function (e) {
            if (hoverTableLine != null) {
                $('#tableJoinMenu').attr('editLine', hoverTableLine);
                var pointX = e.pageX - $('#tableRelaCanvas').offset().left;
                var pointY = e.pageY - $('#tableRelaCanvas').offset().top;
                var lineJoinType = tableJoinMap[hoverTableLine] || 0;
                $('#tableJoinMenu').find('.selectTableMenuItem').removeClass('selectTableMenuItem');
                $('#tableJoinMenu').find('.tableMenuItem[type="' + lineJoinType + '"]').addClass('selectTableMenuItem');
                $('#tableJoinMenu').css({left: pointX, top: pointY}).show();
            } else if ($(e.target).hasClass('modelTableTitle')) {
                $('#tableTitleMenu').attr('editTable', $(e.target).parent().attr('tableTemp'));
                var pointX = e.pageX - $('#tableRelaCanvas').offset().left;
                var pointY = e.pageY - $('#tableRelaCanvas').offset().top;
                $('#tableTitleMenu').css({left: pointX, top: pointY}).show();
            }
            return false;
        });
    }

    function checkPointInLine(pointX, pointY, startPoint, stopPoint) {
        if (startPoint[0] > stopPoint[0] && (pointX > startPoint[0] || pointX < stopPoint[0])) return false;
        if (startPoint[0] < stopPoint[0] && (pointX > stopPoint[0] || pointX < startPoint[0])) return false;
        if (startPoint[1] > stopPoint[1] && (pointY > startPoint[1] || pointY < stopPoint[1])) return false;
        if (startPoint[1] < stopPoint[1] && (pointY > stopPoint[1] || pointY < startPoint[1])) return false;
        var lineLength = Math.sqrt(Math.pow(startPoint[0] - stopPoint[0], 2) + Math.pow(startPoint[1] - stopPoint[1], 2));
        var startPointLen = Math.sqrt(Math.pow(startPoint[0] - pointX, 2) + Math.pow(startPoint[1] - pointY, 2));
        var stopPointLen = Math.sqrt(Math.pow(stopPoint[0] - pointX, 2) + Math.pow(stopPoint[1] - pointY, 2));
        if (Math.abs(lineLength - startPointLen - stopPointLen) < 0.1) return true;
        return false;
    }

    function bindDSTableTreeEvent() {
        $('#dsTableTreeArea .selfTreeNode[isLeaf=1]').unbind();
        $('#dsTableTreeArea .selfTreeNode[isLeaf=1]').mousedown(function (e) {
            e = e || window.event;
            mouseX = e.pageX, mouseY = e.pageY;
            var tableName = $(this).attr('id'), tableComment = $.trim($(this).find('.selfTreeText').text());
            isDragTable = true;
            $('#dragTableViewDiv').attr('tableName', tableName).text(tableComment);
            $('#dragTableViewDiv').css({top: mouseY + 2, left: mouseX + 2}).show();
        });
    }

    function addDSTable2Model(tableName, tableComment) {
        var dsNO = $('#dsConnectCombo').val();
        $.ajax({
            url: "dataSourceController/getTableColumnList",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({dsNO: dsNO, tableName: tableName}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                var tableTemp = "A" + tableIndex;
                createTableModelEle(tableName, tableTemp, tableComment, data.respData);
                tableIndex++;
            }
        })
    }

    function createTableModelEle(tableName, tableTemp, tableComment, columnList) {
        tableComment = tableComment==''||tableComment==null?tableName:tableComment;
        var tableHTML = "<div tableName='" + tableName + "' tableTemp='" + tableTemp + "' class='modelTableItem' style='left:" + mouseX + "px;top:" + mouseY + "px;'>"
                + "    <div class='modelTableJust' style='left:-3px;top:-3px;cursor:nw-resize;' type='nw'></div>"
                + "    <div class='modelTableJust' style='left:50%;top:-3px;cursor:n-resize;' type='n'></div>"
                + "    <div class='modelTableJust' style='right:-3px;top:-3px;cursor:ne-resize;' type='ne'></div>"
                + "    <div class='modelTableJust' style='left:-3px;top:50%;cursor:w-resize;' type='w'></div>"
                + "    <div class='modelTableJust' style='right:-3px;top:50%;cursor:e-resize;' type='e'></div>"
                + "    <div class='modelTableJust' style='left:-3px;bottom:-4px;cursor:sw-resize;' type='sw'></div>"
                + "    <div class='modelTableJust' style='left:50%;bottom:-4px;cursor:s-resize;' type='s'></div>"
                + "    <div class='modelTableJust' style='right:-3px;bottom:-4px;cursor:se-resize;' type='se'></div>"
                + "    <div class='modelTableTitle'>" + tableComment + "（" + tableTemp + "）</div>"
                + "    <div class='modelTableColumn' style='height:230px;'>";
        for (var i = 0; i < columnList.length; i++) {
            var columnInfo = columnList[i];
            var colName = columnInfo[0], colComment = columnInfo[1], colType = columnInfo[2];
            colComment = checkEmpty(colComment) ? colName : colComment;
            var columnClass = "textTableColumn";
            if (colType == "1") {
                columnClass = "stringTableColumn";
            } else if (colType == "2") {
                columnClass = "numberTableColumn";
            } else if (colType == "3") {
                columnClass = "dateTableColumn";
            }
            tableHTML += "<div class='tableColumnCommon " + columnClass + "' colName='" + colName + "' colComment='" + colComment + "' colType='" + colType + "'>" + colComment + "</div>";
        }
        tableHTML += "    </div>"
                + "</div>";
        $('#modelDefineTableArea').append(tableHTML);
        bindModelTableEvent();
    }

    function bindModelTableEvent() {
        $('#modelDefineTableArea').find('.modelTableItem').unbind();
        $('#modelDefineTableArea').find('.modelTableItem').hover(
                function () {
                    $(this).find('.modelTableJust').show();
                },
                function () {
                    $(this).find('.modelTableJust').hide();
                }
        );
        $('#modelDefineTableArea').find('.modelTableTitle').unbind();
        $('#modelDefineTableArea').find('.modelTableTitle').mousedown(function (e) {
            mouseX = e.pageX, mouseY = e.pageY;
            isDragModel = true;
            dragModelEle = $(this).parent();
        });
        $('#modelDefineTableArea').find('.modelTableJust').unbind();
        $('#modelDefineTableArea').find('.modelTableJust').mousedown(function (e) {
            mouseX = e.pageX, mouseY = e.pageY;
            resizeTableType = $(this).attr('type');
            dragModelEle = $(this).parent();
        });
        $('#modelDefineTableArea').find('.modelTableColumn').unbind();
        $('#modelDefineTableArea').find('.modelTableColumn').scroll(function (e) {
            mouseX = e.pageX, mouseY = e.pageY;
            refreshCanvasRelation();
        });
        $('#modelDefineTableArea').find('.tableColumnCommon').unbind();
        $('#modelDefineTableArea').find('.tableColumnCommon').mousedown(function (e) {
            var tableTemp = $(this).parent().parent().attr('tableTemp'), tableColumn = $(this).attr('colName');
            if (isDrawJoin) {
                if (startJoinCol.indexOf(tableTemp + ".") == 0) {//切换列
                    startJoinCol = tableTemp + "." + tableColumn;
                } else {
                    var checkSort = 1, checkJoinType = 0;
                    var joinStartTemp = startJoinCol.split('.')[0];
                    for (var relaCode in tableJoinMap) {
                        var relaInfo = relaCode.split('-');
                        var startInfo = relaInfo[0], stopInfo = relaInfo[1];
                        if (startInfo.indexOf(tableTemp + ".") != -1 && stopInfo.indexOf(joinStartTemp + ".") != -1) {
                            checkSort = 2;
                            checkJoinType = tableJoinMap[relaCode];
                            break;
                        } else if (startInfo.indexOf(joinStartTemp + ".") != -1 && stopInfo.indexOf(tableTemp + ".") != -1) {
                            checkSort = 1;
                            checkJoinType = tableJoinMap[relaCode];
                            break;
                        }
                    }
                    if (checkSort == 2) {
                        tableJoinMap[tableTemp + "." + tableColumn + "-" + startJoinCol] = checkJoinType;
                    } else {
                        tableJoinMap[startJoinCol + "-" + tableTemp + "." + tableColumn] = checkJoinType;
                    }
                    isDrawJoin = false;
                    startJoinCol = null;
                    mouseX = e.pageX, mouseY = e.pageY;
                    refreshCanvasRelation();
                }
            } else {
                isDrawJoin = true;
                startJoinCol = tableTemp + "." + tableColumn;
            }
        });
    }

    function refreshCanvasRelation() {
        var canvas2D = drawJoinCanvas.getContext("2d");
        canvas2D.clearRect(0, 0, drawJoinCanvas.width, drawJoinCanvas.height);
        for (var relaCode in tableJoinMap) {
            var relaType = tableJoinMap[relaCode];
            var relaInfo = relaCode.split('-');
            var startInfo = relaInfo[0].split('.'), stopInfo = relaInfo[1].split('.');
            var startTable = startInfo[0], startColumn = startInfo[1];
            var stopTable = stopInfo[0], stopColumn = stopInfo[1];
            var startEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + startTable + '"]');
            var stopsEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + stopTable + '"]');
            var startEleLeft = startEles[0].offsetLeft, startEleTop = startEles[0].offsetTop;
            var stopsEleLeft = stopsEles[0].offsetLeft, stopsEleTop = stopsEles[0].offsetTop;
            var startEleWidth = startEles.width(), stopsEleWidth = stopsEles.width();
            var startEleScroll = startEles.find('.modelTableColumn')[0].scrollTop;
            var stopsEleScroll = stopsEles.find('.modelTableColumn')[0].scrollTop;
            var startColEle = startEles.find('.tableColumnCommon[colName="' + startColumn + '"]');
            var stopsColEle = stopsEles.find('.tableColumnCommon[colName="' + stopColumn + '"]');
            var startColY = startColEle.prevAll().length * 26 + 14, stopsColY = stopsColEle.prevAll().length * 26 + 14;
            var startPointY = startEleTop, stopsPointY = stopsEleTop;
            if (startEleScroll > startColY) {//字段滚动距离大于当前所在位置则直接连接到最上方
                startPointY = startEleTop;
            } else if (startEleScroll + startEles.height() - 30 < startColY) {//字段滚动距离+字段区域高度小于当前所在位置则连接到最下方
                startPointY = startEleTop + startEles.height();
            } else {//在可视区域内，
                startPointY = startEleTop + 30 + startColY - startEleScroll;
            }
            if (stopsEleScroll > stopsColY) {//字段滚动距离大于当前所在位置则直接连接到最上方
                stopsPointY = stopsEleTop;
            } else if (stopsEleScroll + stopsEles.height() - 30 < stopsColY) {//字段滚动距离+字段区域高度小于当前所在位置则连接到最下方
                stopsPointY = stopsEleTop + stopsEles.height();
            } else {//在可视区域内，
                stopsPointY = stopsEleTop + 30 + stopsColY - stopsEleScroll;
            }
            var startPointX = startEleLeft, stopsPointX = stopsEleLeft;
            var joinOffset = 12;
            if (startPointX > stopsPointX) {
                stopsPointX = stopsPointX + stopsEleWidth;
                if (relaType == 1) joinOffset = -12;
            } else if (startPointX < stopsPointX) {
                startPointX = startPointX + startEleWidth;
                if (relaType == 2) joinOffset = -12;
            }
            var xStepLength = (stopsPointX - startPointX) / 3;
            canvas2D.beginPath();
            canvas2D.moveTo(startPointX, startPointY);
            canvas2D.lineTo(startPointX + xStepLength, startPointY);
            canvas2D.lineTo(stopsPointX - xStepLength, stopsPointY);
            canvas2D.lineTo(stopsPointX, stopsPointY);
            if (relaType == 1) {
                canvas2D.moveTo(startPointX + joinOffset, startPointY - 6);
                canvas2D.lineTo(startPointX, startPointY);
                canvas2D.lineTo(startPointX + joinOffset, startPointY + 6);
            } else if (relaType == 2) {
                canvas2D.moveTo(stopsPointX + joinOffset, stopsPointY - 6);
                canvas2D.lineTo(stopsPointX, stopsPointY);
                canvas2D.lineTo(stopsPointX + joinOffset, stopsPointY + 6);
            }
            canvas2D.strokeStyle = hoverTableLine == relaCode ? '#F6CB84' : 'red';
            canvas2D.lineWidth = 2;
            canvas2D.stroke();
            tableJoinPoint[relaCode] = [[startPointX, startPointY], [startPointX + xStepLength, startPointY], [stopsPointX - xStepLength, stopsPointY], [stopsPointX, stopsPointY]];
        }
        if (isDrawJoin) {
            var startInfo = startJoinCol.split('.');
            var startTable = startInfo[0], startColumn = startInfo[1];
            var startEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + startTable + '"]');
            var startEleLeft = startEles[0].offsetLeft, startEleTop = startEles[0].offsetTop;
            var startEleWidth = startEles.width();
            var startEleScroll = startEles.find('.modelTableColumn')[0].scrollTop;
            var startColEle = startEles.find('.tableColumnCommon[colName="' + startColumn + '"]');
            var startColY = startColEle.prevAll().length * 26 + 14;
            var startPointY = startEleTop, startPointX = startEleLeft;
            if (startEleScroll > startColY) {//字段滚动距离大于当前所在位置则直接连接到最上方
                startPointY = startEleTop;
            } else if (startEleScroll + startEles.height() - 30 < startColY) {//字段滚动距离+字段区域高度小于当前所在位置则连接到最下方
                startPointY = startEleTop + startEles.height();
            } else {//在可视区域内，
                startPointY = startEleTop + 30 + startColY - startEleScroll;
            }
            var mousePointX = mouseX - $('#tableRelaCanvas').offset().left;
            var mousePointY = mouseY - $('#tableRelaCanvas').offset().top;
            if (startPointX + startEleWidth / 2 < mousePointX) startPointX = startPointX + startEleWidth;
            var xStepLength = (mousePointX - startPointX) / 3;
            canvas2D.beginPath();
            canvas2D.moveTo(startPointX, startPointY);
            canvas2D.lineTo(startPointX + xStepLength, startPointY);
            canvas2D.lineTo(mousePointX - xStepLength, mousePointY);
            canvas2D.lineTo(mousePointX, mousePointY);
            canvas2D.strokeStyle = 'red';
            canvas2D.lineWidth = 2;
            canvas2D.stroke();
        }
    }

    function changeTableJoinType(joinType) {
        var editRelaLine = $('#tableJoinMenu').attr('editLine');
        var editRelaInfo = editRelaLine.split('-');
        var editRelaStart = editRelaInfo[0].split('.'), editRelaStops = editRelaInfo[1].split('.');
        var findKeys = editRelaStart[0] + '.' + editRelaStops[0] + ".";
        for (var relaCode in tableJoinMap) {
            var relaInfo = relaCode.split('-');
            var startInfo = relaInfo[0].split('.'), stopInfo = relaInfo[1].split('.');
            var thisKeys = startInfo[0] + '.' + stopInfo[0] + ".";
            if (findKeys == thisKeys) {
                tableJoinMap[relaCode] = joinType;
            }
        }
        $('#tableJoinMenu').removeAttr('editLine').hide();
        isDrawJoin = false;
        refreshCanvasRelation();
    }

    function deleteTableJoins() {
        var relaCode = $('#tableJoinMenu').attr('editLine');
        tableJoinMap = delMapByKey(tableJoinMap, relaCode);
        tableJoinPoint = delMapByKey(tableJoinPoint, relaCode);
        $('#tableJoinMenu').removeAttr('editLine').hide();
        isDrawJoin = false;
        refreshCanvasRelation();
    }

    function filterModelTable() {
        var editTable = $('#tableTitleMenu').attr('editTable');
        $('#tableTitleMenu').removeAttr('editTable').hide();
        var prevFilterSet = tableFilter[editTable] || [];
        var tableColList = [];
        $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + editTable + '"]').find('.tableColumnCommon').each(function (e) {
            var thisColumn = $(this).attr('colName'), thisComment = $(this).attr('colComment'), thisType = $(this).attr('colType');
            tableColList.push([thisColumn, thisComment == "" ? thisColumn : thisComment, thisType]);
        });
        showFrameDialog("pgTableFilterSet.html", {title: '过滤设置', width: 800, height: 340}, {tableCols: tableColList, tableFilter: prevFilterSet}, function (param) {
            if (param) tableFilter[editTable] = param;
        });
    }

    function deleteModelTable() {
        var editTable = $('#tableTitleMenu').attr('editTable');
        $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + editTable + '"]').remove();
        var delKeyList = [];
        for (var relaCode in tableJoinMap) {
            var relaInfo = relaCode.split('-');
            var startInfo = relaInfo[0], stopInfo = relaInfo[1];
            if (startInfo.indexOf(editTable + '.') != -1 || stopInfo.indexOf(editTable + ".") != -1) {
                delKeyList.push(relaCode);
            }
        }
        tableJoinMap = delMapByKeys(tableJoinMap, delKeyList);
        tableJoinPoint = delMapByKeys(tableJoinPoint, delKeyList);
        tableFilter = delMapByKey(tableFilter, editTable);
        $('#tableTitleMenu').removeAttr('editTable').hide();
        isDrawJoin = false;
        refreshCanvasRelation();
    }

    function showModelDefineCreate(clickTab) {
        if ($(clickTab).hasClass('modelDefineSelectTab')) return;
        $('.modelDefineSelectTab').removeClass('modelDefineSelectTab');
        $(clickTab).addClass('modelDefineSelectTab');
        $('#modelDefineCreateDiv').show();
        $('#modelDefineDatasDiv').hide();
        $('#modelDefineSQLDiv').hide();
    }

    function showModelDefineDatas(clickTab) {
        modelDefine = checkModelDefine();
        if (!modelDefine) return;
        if ($(clickTab).hasClass('modelDefineSelectTab')) return;
        $('.modelDefineSelectTab').removeClass('modelDefineSelectTab');
        $(clickTab).addClass('modelDefineSelectTab');
        $('#modelDefineCreateDiv').hide();
        $('#modelDefineDatasDiv').show();
        $('#modelDefineSQLDiv').hide();
        var modelTables = modelDefine.joinSort;
        var tableColumns = [];
        for (var i = 0; i < modelTables.length; i++) {
            var tableTemp = modelTables[i][0];
            var tableEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + tableTemp + '"]');
            tableEles.find('.tableColumnCommon').each(function (e) {
                var thisColumn = $(this).attr('colName'), thisComment = $(this).attr('colComment'),
                        thisType = $(this).attr('colType');
                thisComment = thisComment == "" ? (tableTemp + "." + thisColumn) : (tableTemp + "." + thisComment);
                tableColumns.push({
                    field: tableTemp + '_' + thisColumn,
                    title: thisComment,
                    width: 120,
                    align: (thisType == 1 ? "left" : (thisType == 2 ? "right" : "center"))
                });
            });
        }
        viewTable = new DataTable('modelDefineDatasDiv', tableColumns, refreshModelViewTable);
        refreshModelViewTable();
    }

    function refreshModelViewTable() {
        var dsNO = $('#dsConnectCombo').val();
        var pageLimit = viewTable.getPageLimit();
        var tableTempMap = {}, tableColsMap = {};
        $('#modelDefineTableArea').find('.modelTableItem').each(function (e) {
            var tableTemp = $(this).attr('tableTemp');
            tableTempMap[tableTemp] = $(this).attr('tableName');
            var thisColList = [];
            $(this).find('.tableColumnCommon').each(function (e) {
                thisColList.push([$(this).attr('colName'), $(this).attr('colComment'), $(this).attr('colType')]);
            });
            tableColsMap[tableTemp] = thisColList;
        });
        $.ajax({
            url: "dataSourceController/getViewTableData",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({"dsNO": dsNO, "tableTemp": tableTempMap, "tableCols": tableColsMap, "tableFilter": tableFilter, "modelDefine": modelDefine, "pageLimit": pageLimit}),
            contentType: "application/json",
            success: function (data, status, xhr) {
                viewTable.setTableData(data.respData);
            }
        })
    }

    function showModelDefineSQL(clickTab) {
        modelDefine = checkModelDefine();
        if (!modelDefine) return;
        if ($(clickTab).hasClass('modelDefineSelectTab')) return;
        $('.modelDefineSelectTab').removeClass('modelDefineSelectTab');
        $(clickTab).addClass('modelDefineSelectTab');
        $('#modelDefineCreateDiv').hide();
        $('#modelDefineDatasDiv').hide();
        $('#modelDefineSQLDiv').show();
        var colsMapping = {};
        var modelTables = modelDefine.joinSort, modelJoins = modelDefine.joinCols;
        var columnSql = "", fromSql = "", whereSql = "";
        for (var i = 0; i < modelTables.length; i++) {
            var tableTemp = modelTables[i][0], tableJoin = modelTables[i][1];
            var tableEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + tableTemp + '"]');
            var tableName = tableEles.attr('tableName');
            tableEles.find('.tableColumnCommon').each(function (e) {
                var thisColumn = $(this).attr('colname');
                if (columnSql.length > 0) columnSql += ",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                columnSql += tableTemp + "." + thisColumn + "&nbsp;&nbsp;";
                var colAlias = tableTemp + "_" + thisColumn;
                columnSql += colsMapping[colAlias] || colAlias;
            });
            if (tableJoin == -1) {
                fromSql += tableName + "&nbsp;&nbsp;" + tableTemp;
                whereSql = getTableFilterSQL(tableTemp);
            } else {
                fromSql += "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                if (tableJoin == 1) {
                    fromSql += "LEFT JOIN&nbsp;&nbsp;";
                } else if (tableJoin == 2) {
                    fromSql += "RIGHT JOIN&nbsp;&nbsp;";
                } else {
                    fromSql += "INNER JOIN&nbsp;&nbsp;";
                }
                fromSql += tableName + "&nbsp;&nbsp;" + tableTemp + "&nbsp;&nbsp;ON&nbsp;&nbsp;";
                var thisJoins = modelJoins[tableTemp];
                for (var j = 0; j < thisJoins.length; j++) {
                    fromSql += (j == 0 ? "" : "&nbsp;&nbsp;AND&nbsp;&nbsp;") + thisJoins[j];
                }
                var filterSQL = getTableFilterSQL(tableTemp);
                fromSql += (filterSQL.length == 0 ? "" : "&nbsp;&nbsp;AND&nbsp;&nbsp;") + filterSQL;
            }
        }
        var viewSql = "&nbsp;SELECT&nbsp;&nbsp;" + columnSql + "<br>&nbsp;&nbsp;&nbsp;FROM&nbsp;&nbsp;"
                + fromSql + (whereSql.length == 0 ? "" : "<br>&nbsp;&nbsp;WHERE&nbsp;&nbsp;") + whereSql;
        $('#modelDefineSQLDiv').html(viewSql);
    }

    function getTableFilterSQL(tableName) {
        var filterSet = tableFilter[tableName];
        var filterSQL = "";
        if (filterSet && filterSet.length > 0) {
            var multiTypeMap = {}, colFilterMap = {};
            for (var i = 0; i < filterSet.length; i++) {
                //[colName, colComment, multiType, relaType, filterVal, sortNO]
                var filterInfo = filterSet[i];
                multiTypeMap[filterInfo[0]] = filterInfo[2];
                var colFilters = colFilterMap[filterInfo[0]] || [];
                colFilters.push([filterInfo[3], filterInfo[4]]);
                colFilterMap[filterInfo[0]] = colFilters;
            }
            var tableEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + tableName + '"]');
            for (var filterCol in colFilterMap) {
                var multiType = multiTypeMap[filterCol];
                var colFilters = colFilterMap[filterCol];
                var colType = tableEles.find('.tableColumnCommon[colName="' + filterCol + '"]').attr('colType');
                var multiTypeName = multiType == '1' ? '' : (multiType == '2' ? '&nbsp;&nbsp;OR&nbsp;&nbsp;' : '&nbsp;&nbsp;AND&nbsp;&nbsp;');
                var valQuate = colType == "2" ? "" : "'";
                var colWhere = "";
                for (var i = 0; i < colFilters.length; i++) {
                    if (i > 0) colWhere += multiTypeName;
                    var relaType = colFilters[i][0], filterVal = colFilters[i][1];
                    if (relaType == '1') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;=&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '2') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;<>&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '3') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;>&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '4') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;>=&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '5') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;<&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '6') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;<=&nbsp;&nbsp;' + valQuate + filterVal + valQuate;
                    } else if (relaType == '7') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;LIKE&nbsp;&nbsp;' + valQuate + "%" + filterVal + "%" + valQuate;
                    } else if (relaType == '8') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;NOT&nbsp;&nbsp;LIKE&nbsp;&nbsp;' + valQuate + "%" + filterVal + "%" + valQuate;
                    } else if (relaType == '9') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;LIKE&nbsp;&nbsp;' + valQuate + filterVal + "%" + valQuate;
                    } else if (relaType == '10') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;LIKE&nbsp;&nbsp;' + valQuate + "%" + filterVal + valQuate;
                    } else if (relaType == '11') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;IS&nbsp;&nbsp;NULL';
                    } else if (relaType == '12') {
                        colWhere += tableName + '.' + filterCol + '&nbsp;&nbsp;IS&nbsp;&nbsp;NOT&nbsp;&nbsp;NULL';
                    } else if (relaType == '13') {
                        colWhere += tableName + '.' + filterCol + "&nbsp;&nbsp;=&nbsp;&nbsp;''";
                    } else if (relaType == '14') {
                        colWhere += tableName + '.' + filterCol + "&nbsp;&nbsp;<>&nbsp;&nbsp;''";
                    }
                }
                filterSQL += (filterSQL.length == 0 ? "" : "&nbsp;&nbsp;AND&nbsp;&nbsp;") + (colFilters.length > 1 ? "(" : "") + colWhere + (colFilters.length > 1 ? ")" : "");
            }
        }
        return filterSQL;
    }

    function checkModelDefine() {
        var modelTableEles = $('#modelDefineTableArea').find('.modelTableItem');
        var modelTableCount = modelTableEles.length;
        if (modelTableCount == 0) {
            showWarnDialog("请先设置数据模型！");
            return false;
        }
        if (modelTableCount == 1) return {"joinSort": [[modelTableEles.attr('tableTemp'), '-1']], "joinCols": {}};
        //  前后关联关系及关联方式       表格关联关系                                 节点前置节点列表                      节点下一节点列表                      可作为主表的列表                            从表列表                                            从表关联字段
        var tableJoins = {}, tableJoinKey = [], nodePrevMap = {}, nodeNextMap = {}, mainTableList = [],
                relaTableList = [], tableJoinCols = {};
        for (var relaCode in tableJoinMap) {
            var relaType = tableJoinMap[relaCode];
            var relaInfo = relaCode.split('-');
            var startInfo = relaInfo[0], stopInfo = relaInfo[1];
            var startTemp = startInfo.split('.')[0], stopTemp = stopInfo.split('.')[0];
            var startCols = startInfo.split('.')[1], stopCols = stopInfo.split('.')[1];
            var stopJoinCols = tableJoinCols[stopTemp] || [];
            stopJoinCols.push(startTemp + "." + startCols + " = " + stopTemp + "." + stopCols);
            tableJoinCols[stopTemp] = stopJoinCols;
            if (relaType == 0) {
                var startJoinCols = tableJoinCols[startTemp] || [];
                startJoinCols.push(stopTemp + "." + stopCols + " = " + startTemp + "." + startCols);
                tableJoinCols[startTemp] = startJoinCols;
            }
            if (tableJoinKey.indexOf(startTemp + '-' + stopTemp) == -1) {
                tableJoins[stopTemp] = relaType;
                tableJoinKey.push(startTemp + '-' + stopTemp);
                var stopPrevList = nodePrevMap[stopTemp] || [];
                var startNextList = nodeNextMap[startTemp] || [];
                if (stopPrevList.indexOf(startTemp) == -1) stopPrevList.push(startTemp);
                if (startNextList.indexOf(stopTemp) == -1) startNextList.push(stopTemp);
                nodePrevMap[stopTemp] = stopPrevList;
                nodeNextMap[startTemp] = startNextList;
                if (relaType != 0) {//左右连接，左侧作为主表，右侧作为关联表
                    if (mainTableList.indexOf(startTemp) == -1) mainTableList.push(startTemp);
                    if (relaTableList.indexOf(stopTemp) == -1) relaTableList.push(stopTemp);
                } else {//内连接
                    if (mainTableList.indexOf(startTemp) == -1) mainTableList.push(startTemp);
                    if (mainTableList.indexOf(stopTemp) == -1) mainTableList.push(stopTemp);
                    //内连接可互做前置节点
                    var stopNextList = nodeNextMap[stopTemp] || [];
                    var startPrevList = nodePrevMap[startTemp] || [];
                    if (stopNextList.indexOf(startTemp) == -1) stopNextList.push(startTemp);
                    if (startPrevList.indexOf(stopTemp) == -1) startPrevList.push(stopTemp);
                    nodePrevMap[startTemp] = startPrevList;
                    nodeNextMap[stopTemp] = stopNextList;
                }
            }
        }
        //校验是否全都关联，能找到所有节点则认为全部连接
        var checkIndex = 0, existList = [];
        while (tableJoinKey.length > 0) {
            var leftJoinKey = [];
            var searchBefore = tableJoinKey.length;
            for (var i = 0; i < tableJoinKey.length; i++) {
                var joinKeys = tableJoinKey[i].split('-');
                if (checkIndex == 0 || existList.includes(joinKeys[0]) || existList.includes(joinKeys[1])) {
                    if (!existList.includes(joinKeys[0])) existList.push(joinKeys[0]);
                    if (!existList.includes(joinKeys[1])) existList.push(joinKeys[1]);
                } else {
                    leftJoinKey.push(tableJoinKey[i]);
                }
                checkIndex++;
            }
            //已全部找到，或者部分无法找到
            if (leftJoinKey.length == 0 || searchBefore == leftJoinKey.length) break;
            tableJoinKey = leftJoinKey;
        }
        if (existList.length != modelTableCount) {
            showWarnDialog("存在数据表未设置关联关系！");
            return false;
        }
        //校验同一个表是否被其他表同时左关联或者右关联，内连接时无需处理（可交换关联）,去除被其他表关联的主表
        var leftMainList = deleteArrayKeys(mainTableList, relaTableList);
        if (leftMainList.length == 0) {
            showWarnDialog("数据表关联关系不可形成关联闭环！");
            return false;
        }
        leftMainList.sort();
        //以任意主表作为开始表生成sql，若无法连接全部表则错误
        var tableJoinSort = [];//数据格式[[临时表ID, 关联方式],[临时表ID, 关联方式],...]
        for (var i = 0; i < leftMainList.length; i++) {
            var thisMain = leftMainList[i];
            //当前主表存在前置节点则不可作为开始主表
            //if(nodePrevMap[thisMain]&&nodePrevMap[thisMain].length>0) continue;
            var nodePrevTemp = JSON.parse(JSON.stringify(nodePrevMap));
            var nodeNextTemp = JSON.parse(JSON.stringify(nodeNextMap));
            var joinedList = [thisMain];//已添加连接表
            tableJoinSort = [[thisMain, -1]];//主表，无关联方式设置为-1
            var nextNodeList = nodeNextTemp[thisMain];
            var cycleNextList = [];//递归下一层级
            //清空后续节点的前置节点依赖，用于判断是否满足拼接条件
            nodePrevTemp = removePrevNodeRela(nodePrevTemp, thisMain);
            var isFindAll = true;
            while (nextNodeList.length > 0) {
                var nextNodeCount = nextNodeList.length;
                for (var j = 0; j < nextNodeList.length; j++) {
                    var nextNode = nextNodeList[j];
                    if (nodePrevTemp[nextNode].length == 0) {
                        tableJoinSort.push([nextNode, tableJoins[nextNode] || 0]);
                        nodePrevTemp = removePrevNodeRela(nodePrevTemp, nextNode);
                        if (nodeNextTemp[nextNode]) {
                            cycleNextList = cycleNextList.concat(nodeNextTemp[nextNode]);
                        }
                        nextNodeList = deleteArrayKeys(nextNodeList, [nextNode]);
                        if (joinedList.indexOf(nextNode) == -1) joinedList.push(nextNode);
                    }
                }
                if (nextNodeCount == nextNodeList.length) {
                    isFindAll = false;
                    break;
                }
                if (nextNodeList.length == 0) {
                    cycleNextList = deleteArrayKeys(nextNodeList, joinedList);
                    nextNodeList = cycleNextList;
                    cycleNextList = [];
                }
            }
            if (isFindAll && tableJoinSort.length == modelTableCount) break;
        }
        if (tableJoinSort.length != modelTableCount) {
            showWarnDialog("关联表只能有一个主表，请检查！");
            return false;
        }
        return {"joinSort": tableJoinSort, "joinCols": tableJoinCols};
    }

    function removePrevNodeRela(nodePrevMap, removeKey) {
        for (var nodeName in nodePrevMap) {
            nodePrevMap[nodeName] = deleteArrayKeys(nodePrevMap[nodeName], [removeKey]);
        }
        return nodePrevMap;
    }

    function saveInterfaceDefine() {
        //{"joinSort":tableJoinSort, "joinCols":tableJoinCols};
        modelDefine = checkModelDefine();
        if (!modelDefine) return;
        showFrameDialog("pgInterfaceSaveSet.html", {title: '保存数据模型', width: 600, height: 300}, {modelID: serverID}, function (saveParam) {
            if (saveParam) {
                runInterfaceDefineSave(saveParam);
            }
        });
    }

    function runInterfaceDefineSave(serverInfo) {
        var dsNO = $('#dsConnectCombo').val();
        var tableInfo = [], tableColInfo = [];
        var tableTempMap = {}, columnTempMap = {};
        for (var i = 0; i < modelDefine.joinSort.length; i++) {
            var tableJoin = modelDefine.joinSort[i];
            var tableTemp = tableJoin[0], joinType = tableJoin[1];
            var tableEles = $('#modelDefineTableArea').find('.modelTableItem[tableTemp="' + tableTemp + '"]');
            var tableName = tableEles.attr('tableName');
            var tableComment = $.trim($('#dsTableTreeArea').find('#' + tableName + '>.selfTreeText').text());
            var tableLeft = tableEles[0].offsetLeft, tableTop = tableEles[0].offsetTop;
            tableInfo.push({
                tableName: tableName, tableComment: tableComment, tableTemp: tableTemp, dsNO: dsNO, joinType: joinType,
                tableLeft: tableLeft, tableTop: tableTop, tableSort: i + 1
            });
            tableEles.find('.tableColumnCommon').each(function (e) {
                var colName = $(this).attr('colName'), colComment = $(this).attr('colComment'),
                        colType = $(this).attr('colType');
                tableColInfo.push([colName, colComment, colType, tableTemp + '_' + colName, tableName, tableComment, tableTemp, dsNO, e + 1]);
                columnTempMap[tableTemp + '_' + colName] = colComment;
            });
            tableTempMap[tableTemp] = tableName;
        }
        var tableJoinInfo = [];
        for (var joinKey in tableJoinMap) {
            var joinType = tableJoinMap[joinKey] + "";
            var relaInfo = joinKey.split('-');
            var startInfo = relaInfo[0], stopInfo = relaInfo[1];
            var startTemp = startInfo.split('.')[0], stopTemp = stopInfo.split('.')[0];
            var startCols = startInfo.split('.')[1], stopCols = stopInfo.split('.')[1];
            tableJoinInfo.push([tableTempMap[startTemp], startTemp, startCols, columnTempMap[startTemp + "_" + startCols],
                tableTempMap[stopTemp], stopTemp, stopCols, columnTempMap[stopTemp + "_" + stopCols], joinType]);
        }
        var tableFilterInfo = [];
        for (var tableTemp in tableFilter) {
            var filterList = tableFilter[tableTemp];
            for (var i = 0; i < filterList.length; i++) {
                tableFilterInfo.push([tableTempMap[tableTemp], tableTemp, filterList[i][0], filterList[i][1], filterList[i][2], filterList[i][3], filterList[i][4], filterList[i][5]]);
            }
        }
        var inputParamInfo = [];
        $('#inputParamSetting').find('.tableColumnCommon').each(function (e) {
            var colName = $(this).attr('colName'), colComment = $(this).attr('colComment'),
                    colType = $(this).attr('colType');
            var compType = $(this).attr('compType'), compName = $(this).attr('compName'),
                    colShow = $.trim($(this).text());
            var originTableTemp = colName.substring(0, colName.indexOf('_')),
                    originColName = colName.substring(colName.indexOf('_') + 1);
            inputParamInfo.push([colName, colComment, colType, colShow, tableTempMap[originTableTemp], originTableTemp, originColName, compType, compName, e + 1]);
        });
        var outputColumnInfo = [];
        $('#returnColumnSetting').find('.tableColumnCommon').each(function (e) {
            var colName = $(this).attr('colName'), colComment = $(this).attr('colComment');
            var colType = $(this).attr('colType'), colShow = $.trim($(this).text());
            var originTableTemp = colName.substring(0, colName.indexOf('_'));
            var originColName = colName.substring(colName.indexOf('_') + 1);
            outputColumnInfo.push([colName, colComment, colType, colShow, tableTempMap[originTableTemp], originTableTemp, originColName, e + 1]);
        });
        serverInfo['dsNO'] = dsNO;
        $.ajax({
            url: "dataSourceController/saveInterfaceInfo",
            type: 'POST',
            dataType: "json",
            data: JSON.stringify({
                serverID: serverID,
                serverGroup: serverGroup,
                serverInfo: serverInfo,
                tableInfo: tableInfo,
                tableColInfo: tableColInfo,
                tableJoinInfo: tableJoinInfo,
                tableFilterInfo: tableFilterInfo
            }),
            contentType: "application/json",
            success: function (data, status, xhr) {
                serverID = data.respData;
                refreshExistServer()
            }
        });
    }

    function refreshPageElement() {
        $('#tableRelaCanvas').attr('width', $('#modelDefineCreateDiv').width()).attr('height', $('#modelDefineCreateDiv').height());
        if (viewTable != null) viewTable.resize();
    }
</script>
</body>
</html>